/*
    一、什么是泛型、泛型有什么作用
    概念：在定义函数、接口、类的过程中，不预先定义类型，而是在使用时候去定义类型这种一种行为称为泛型
    在定义函数，接口、方法的时候你不确定类型的时候
    1）使用any
    当你使用any去定义函数参数的类型的时候，返回值值类型不确定；取消了ts的类型约束
    2）使用泛型
    预先不定义，而是在的时候决定
    二、泛型的使用
    1、泛型在函数中的使用
    1）一个泛型
    语法:function 函数名<T>(参数名:T):T{

    }
    使用：函数名<具体的类型>(实参)
    2）多个泛型：
    语法：function 函数名<T,K>(参数名1:T,参数名:K):K{

    }
    使用:函数名<T的具体类型,K的具体类型>(实参1,实参2)
    2、泛型在接口中的使用
    3、泛型在类中的使用
    三、泛型的约束
    泛型的继承
*/
console.log('*********泛型在函数中的使用之单个泛型******************');
function fn1<T>(arg:T):T{
    return arg
}
fn1<string>("Giles")
fn1<number>(123)
fn1<number|string|boolean>(true)
type NewType=number|string|boolean
fn1<NewType>('aaa')
console.log('******泛型在函数中的使用之多个泛型*********************');
function fn2<T,K,Y>(arg1:T,arg2:K,arg3:Y):K{
    return arg2
}
fn2<string,number,boolean>('Giles',23,true)
console.log('******泛型在接口中的定义********************');

interface ISearch{
    <T,K>(arg1:T,arg2:K):K
}
//只限制变量
const fn3:ISearch=(arg1,arg2)=>{
    return arg2
}
//只约束函数本身
const fn4=<T,K>(arg1:T,arg2:K):K=>{
    return arg2
}
// 变量和函数本身都约束
const fn5:ISearch=<T,K>(arg1:T,arg2:K):K=>{
    return arg2
}

fn3<string,number>('Giles',123)
fn4<number,string>(12,'monica')
fn5<boolean,string>(true,'lilu')
console.log('**********泛型在类中的定义***********************');
class Doctor<T,K>{
    name:string;
    telephone:T;
    sex:K;
    constructor(name:string,telephone:T,sex:K){
        this.name=name
        this.telephone=telephone
        this.sex=sex
    }
}

let d1=new Doctor<number,number>('zhangsan',13324537978,1)
let d2=new Doctor<string,string>('lisi','13324567890','男')
console.log('************泛型的继承************************');

class Enginee{
    name:string;
    age:number
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
}
function introduce<T extends Enginee>(arg:T){
    console.log(arg);
}
introduce({name:'张三',age:23,programAge:23})
introduce({name:'张三',age:23,aa:33})

console.log('************泛型在集合中的使用***********************');
let set=new Set<string>()
set.add("Giles")
set.add("Giles")
set.add("Giles")
// set.add(123)
// set.add(['Giles',12,{name:'lily',age:34}])
// console.log(set);

console.log('*******************');
interface Country<T>{
    name:string;
    age:T
}
let map=new Map<string,Country<number>>()

let usa:Country<number>={name:'美利坚合众国',age:300}
map.set('cn','中华人民共和国')
map.set('us',usa)




